"""
课堂质量评估API端点
"""
import base64
import io
from datetime import datetime, timedelta
from typing import List, Dict, Any, Optional
from fastapi import APIRouter, HTTPException, UploadFile, File, Form
from fastapi.responses import JSONResponse
import numpy as np
import cv2
import logging

from backend.schemas.classroom_quality import (
    AttentionAnalysisRequest, AttentionAnalysisResponse,
    ParticipationAnalysisRequest, ParticipationAnalysisResponse,
    ClassroomSessionAnalysisRequest, ClassroomSessionAnalysisResponse,
    LearningPredictionRequest, LearningPredictionResponse,
    StudentAttentionSummaryRequest, StudentAttentionSummaryResponse,
    ClassroomStatisticsRequest, ClassroomStatisticsResponse,
    to_dict
)
from backend.services.classroom_quality_service import ClassroomQualityService

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/classroom-quality", tags=["课堂质量评估"])

# 全局服务实例
classroom_service = ClassroomQualityService()


@router.post("/analyze-attention")
async def analyze_student_attention(
    classroom_id: str = Form(...),
    session_id: str = Form(...),
    student_detections: str = Form(...),  # JSON字符串
    image: UploadFile = File(...)
):
    """
    分析学生专注度
    
    - **classroom_id**: 教室ID
    - **session_id**: 课堂会话ID
    - **student_detections**: 学生检测结果（JSON格式）
    - **image**: 课堂图像文件
    """
    try:
        logger.info(f"开始分析教室 {classroom_id} 会话 {session_id} 的学生专注度")
        
        # 解析学生检测结果
        import json
        detections = json.loads(student_detections)
        
        # 读取图像数据
        image_data = await image.read()
        nparr = np.frombuffer(image_data, np.uint8)
        img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
        
        if img is None:
            raise HTTPException(status_code=400, detail="无法解析图像数据")
        
        # 执行专注度分析
        attention_data_list = await classroom_service.analyze_student_attention(img, detections)
        
        # 计算统计信息
        if attention_data_list:
            avg_attention = np.mean([data.attention_score for data in attention_data_list])
            attention_distribution = {}
            for data in attention_data_list:
                level = data.attention_level.value
                attention_distribution[level] = attention_distribution.get(level, 0) + 1
        else:
            avg_attention = 0
            attention_distribution = {}
        
        # 转换为响应格式
        student_data = []
        for data in attention_data_list:
            student_data.append({
                'student_id': data.student_id,
                'timestamp': data.timestamp.isoformat(),
                'attention_level': data.attention_level.value,
                'attention_score': data.attention_score,
                'behavior': data.behavior.value,
                'confidence': data.confidence,
                'face_direction': data.face_direction,
                'eye_gaze': data.eye_gaze,
                'posture': data.posture
            })
        
        response_data = {
            'analysis_id': f"attention_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
            'classroom_id': classroom_id,
            'session_id': session_id,
            'timestamp': datetime.now().isoformat(),
            'student_attention_data': student_data,
            'average_attention_score': avg_attention,
            'attention_distribution': attention_distribution
        }
        
        logger.info(f"专注度分析完成，分析了 {len(attention_data_list)} 名学生")
        return JSONResponse(content=response_data)
        
    except json.JSONDecodeError:
        raise HTTPException(status_code=400, detail="学生检测结果格式错误")
    except Exception as e:
        logger.error(f"专注度分析失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"专注度分析失败: {str(e)}")


@router.post("/analyze-participation")
async def analyze_student_participation(
    classroom_id: str,
    session_id: str,
    student_ids: List[str],
    audio_features: Optional[Dict[str, Any]] = None
):
    """
    分析学生参与度
    
    - **classroom_id**: 教室ID
    - **session_id**: 课堂会话ID
    - **student_ids**: 学生ID列表
    - **audio_features**: 音频特征（可选）
    """
    try:
        logger.info(f"开始分析教室 {classroom_id} 会话 {session_id} 的学生参与度")
        
        # 执行参与度分析
        participation_data_list = await classroom_service.analyze_student_participation(
            student_ids, audio_features
        )
        
        # 计算统计信息
        if participation_data_list:
            avg_participation = np.mean([data.participation_score for data in participation_data_list])
            participation_distribution = {}
            for data in participation_data_list:
                level = data.participation_level.value
                participation_distribution[level] = participation_distribution.get(level, 0) + 1
        else:
            avg_participation = 0
            participation_distribution = {}
        
        # 转换为响应格式
        student_data = []
        for data in participation_data_list:
            student_data.append({
                'student_id': data.student_id,
                'timestamp': data.timestamp.isoformat(),
                'participation_level': data.participation_level.value,
                'participation_score': data.participation_score,
                'interaction_count': data.interaction_count,
                'hand_raising_count': data.hand_raising_count,
                'speaking_duration': data.speaking_duration,
                'question_asking_count': data.question_asking_count,
                'answer_giving_count': data.answer_giving_count
            })
        
        response_data = {
            'analysis_id': f"participation_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
            'classroom_id': classroom_id,
            'session_id': session_id,
            'timestamp': datetime.now().isoformat(),
            'student_participation_data': student_data,
            'average_participation_score': avg_participation,
            'participation_distribution': participation_distribution
        }
        
        logger.info(f"参与度分析完成，分析了 {len(participation_data_list)} 名学生")
        return JSONResponse(content=response_data)
        
    except Exception as e:
        logger.error(f"参与度分析失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"参与度分析失败: {str(e)}")


@router.post("/analyze-session")
async def analyze_classroom_session(
    classroom_id: str,
    session_id: str,
    start_time: Optional[str] = None,
    end_time: Optional[str] = None
):
    """
    分析课堂会话
    
    - **classroom_id**: 教室ID
    - **session_id**: 课堂会话ID
    - **start_time**: 开始时间（ISO格式，可选）
    - **end_time**: 结束时间（ISO格式，可选）
    """
    try:
        logger.info(f"开始分析教室 {classroom_id} 会话 {session_id}")
        
        # 解析时间范围
        time_range = None
        if start_time and end_time:
            start_dt = datetime.fromisoformat(start_time.replace('Z', '+00:00'))
            end_dt = datetime.fromisoformat(end_time.replace('Z', '+00:00'))
            time_range = (start_dt, end_dt)
        
        # 执行课堂分析
        analysis_result = classroom_service.analyze_classroom_session(
            classroom_id, session_id, time_range
        )
        
        # 转换为响应格式
        response_data = {
            'analysis_id': analysis_result.analysis_id,
            'classroom_id': analysis_result.classroom_id,
            'session_id': analysis_result.session_id,
            'analysis_period': [
                analysis_result.analysis_period[0].isoformat(),
                analysis_result.analysis_period[1].isoformat()
            ],
            'student_count': analysis_result.student_count,
            'average_attention_score': analysis_result.average_attention_score,
            'average_participation_score': analysis_result.average_participation_score,
            'attention_distribution': analysis_result.attention_distribution,
            'participation_distribution': analysis_result.participation_distribution,
            'behavior_statistics': analysis_result.behavior_statistics,
            'classroom_atmosphere': analysis_result.classroom_atmosphere.value,
            'engagement_trends': analysis_result.engagement_trends,
            'learning_effectiveness': analysis_result.learning_effectiveness,
            'recommendations': analysis_result.recommendations
        }
        
        logger.info(f"课堂分析完成，分析ID: {analysis_result.analysis_id}")
        return JSONResponse(content=response_data)
        
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        logger.error(f"课堂分析失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"课堂分析失败: {str(e)}")


@router.post("/predict-learning")
async def predict_student_learning(student_id: str, prediction_period: int = 30):
    """
    预测学生学习效果
    
    - **student_id**: 学生ID
    - **prediction_period**: 预测周期（天数）
    """
    try:
        logger.info(f"开始预测学生 {student_id} 的学习效果")
        
        # 执行学习效果预测
        prediction = classroom_service.predict_student_learning(student_id)
        
        # 转换为响应格式
        response_data = {
            'student_id': prediction.student_id,
            'prediction_id': prediction.prediction_id,
            'predicted_performance': prediction.predicted_performance,
            'risk_level': prediction.risk_level,
            'learning_style': prediction.learning_style,
            'strengths': prediction.strengths,
            'weaknesses': prediction.weaknesses,
            'recommendations': prediction.recommendations,
            'confidence': prediction.confidence,
            'generated_at': datetime.now().isoformat()
        }
        
        logger.info(f"学习效果预测完成，预测ID: {prediction.prediction_id}")
        return JSONResponse(content=response_data)
        
    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e))
    except Exception as e:
        logger.error(f"学习效果预测失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"学习效果预测失败: {str(e)}")


@router.get("/student-attention-summary/{student_id}")
async def get_student_attention_summary(
    student_id: str,
    start_time: Optional[str] = None,
    end_time: Optional[str] = None
):
    """
    获取学生专注度摘要
    
    - **student_id**: 学生ID
    - **start_time**: 开始时间（ISO格式，可选）
    - **end_time**: 结束时间（ISO格式，可选）
    """
    try:
        logger.info(f"获取学生 {student_id} 的专注度摘要")
        
        # 解析时间范围
        time_range = None
        if start_time and end_time:
            start_dt = datetime.fromisoformat(start_time.replace('Z', '+00:00'))
            end_dt = datetime.fromisoformat(end_time.replace('Z', '+00:00'))
            time_range = (start_dt, end_dt)
        
        # 获取专注度摘要
        summary = classroom_service.get_student_attention_summary(student_id, time_range)
        
        if 'error' in summary:
            raise HTTPException(status_code=404, detail=summary['error'])
        
        # 转换时间格式
        if summary.get('time_range'):
            summary['time_range'] = [
                summary['time_range'][0].isoformat(),
                summary['time_range'][1].isoformat()
            ]
        
        logger.info(f"专注度摘要获取完成")
        return JSONResponse(content=summary)
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取专注度摘要失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取专注度摘要失败: {str(e)}")


@router.get("/classroom-statistics/{classroom_id}")
async def get_classroom_statistics(
    classroom_id: str,
    start_time: Optional[str] = None,
    end_time: Optional[str] = None
):
    """
    获取课堂统计信息
    
    - **classroom_id**: 教室ID
    - **start_time**: 开始时间（ISO格式，可选）
    - **end_time**: 结束时间（ISO格式，可选）
    """
    try:
        logger.info(f"获取教室 {classroom_id} 的统计信息")
        
        # 解析时间范围
        time_range = None
        if start_time and end_time:
            start_dt = datetime.fromisoformat(start_time.replace('Z', '+00:00'))
            end_dt = datetime.fromisoformat(end_time.replace('Z', '+00:00'))
            time_range = (start_dt, end_dt)
        
        # 获取课堂统计
        statistics = classroom_service.get_classroom_statistics(classroom_id, time_range)
        
        if 'error' in statistics:
            raise HTTPException(status_code=404, detail=statistics['error'])
        
        # 转换时间格式
        if statistics.get('time_range'):
            statistics['time_range'] = [
                statistics['time_range'][0].isoformat(),
                statistics['time_range'][1].isoformat()
            ]
        
        logger.info(f"课堂统计信息获取完成")
        return JSONResponse(content=statistics)
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取课堂统计失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取课堂统计失败: {str(e)}")


@router.get("/attention-levels")
async def get_attention_levels():
    """获取专注度等级列表"""
    from backend.services.classroom_quality_service import AttentionLevel
    return [level.value for level in AttentionLevel]


@router.get("/participation-levels")
async def get_participation_levels():
    """获取参与度等级列表"""
    from backend.services.classroom_quality_service import ParticipationLevel
    return [level.value for level in ParticipationLevel]


@router.get("/learning-behaviors")
async def get_learning_behaviors():
    """获取学习行为类型列表"""
    from backend.services.classroom_quality_service import LearningBehavior
    return [behavior.value for behavior in LearningBehavior]


@router.get("/classroom-atmospheres")
async def get_classroom_atmospheres():
    """获取课堂氛围类型列表"""
    from backend.services.classroom_quality_service import ClassroomAtmosphere
    return [atmosphere.value for atmosphere in ClassroomAtmosphere]


@router.get("/dashboard/{classroom_id}")
async def get_classroom_dashboard(
    classroom_id: str,
    time_range: str = "24h"  # 1h, 6h, 24h, 7d, 30d
):
    """
    获取课堂仪表板数据
    
    - **classroom_id**: 教室ID
    - **time_range**: 时间范围
    """
    try:
        logger.info(f"获取教室 {classroom_id} 的仪表板数据，时间范围: {time_range}")
        
        # 计算时间范围
        end_time = datetime.now()
        time_deltas = {
            '1h': timedelta(hours=1),
            '6h': timedelta(hours=6),
            '24h': timedelta(days=1),
            '7d': timedelta(days=7),
            '30d': timedelta(days=30)
        }
        
        if time_range not in time_deltas:
            raise HTTPException(status_code=400, detail="无效的时间范围")
        
        start_time = end_time - time_deltas[time_range]
        
        # 获取课堂统计
        statistics = classroom_service.get_classroom_statistics(
            classroom_id, (start_time, end_time)
        )
        
        # 构建仪表板数据
        dashboard_data = {
            'classroom_id': classroom_id,
            'time_range': time_range,
            'generated_at': datetime.now().isoformat(),
            'summary': {
                'average_attention_score': statistics.get('average_attention_score', 0),
                'average_participation_score': statistics.get('average_participation_score', 0),
                'average_learning_effectiveness': statistics.get('average_learning_effectiveness', 0),
                'total_students_analyzed': statistics.get('total_students_analyzed', 0),
                'analysis_count': statistics.get('analysis_count', 0)
            },
            'trends': {
                'attention_score_trend': statistics.get('attention_score_trend', 'stable'),
                'participation_score_trend': statistics.get('participation_score_trend', 'stable')
            },
            'distributions': {
                'atmosphere_distribution': statistics.get('atmosphere_distribution', {}),
                'most_common_atmosphere': statistics.get('most_common_atmosphere', 'average')
            },
            'alerts': [],  # 可以添加告警信息
            'recommendations': []  # 可以添加建议
        }
        
        # 添加基于数据的建议
        if statistics.get('average_attention_score', 0) < 60:
            dashboard_data['recommendations'].append("平均专注度较低，建议增加互动环节")
        
        if statistics.get('average_participation_score', 0) < 50:
            dashboard_data['recommendations'].append("学生参与度不足，建议鼓励更多互动")
        
        logger.info(f"仪表板数据获取完成")
        return JSONResponse(content=dashboard_data)
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取仪表板数据失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取仪表板数据失败: {str(e)}")


@router.delete("/data/{student_id}")
async def clear_student_data(student_id: str):
    """
    清除学生数据
    
    - **student_id**: 学生ID
    """
    try:
        # 清除学生的历史数据
        if student_id in classroom_service.attention_data_storage:
            del classroom_service.attention_data_storage[student_id]
        
        if student_id in classroom_service.participation_data_storage:
            del classroom_service.participation_data_storage[student_id]
        
        # 清除相关的预测数据
        predictions_to_delete = []
        for pred_id, prediction in classroom_service.learning_predictions_storage.items():
            if prediction.student_id == student_id:
                predictions_to_delete.append(pred_id)
        
        for pred_id in predictions_to_delete:
            del classroom_service.learning_predictions_storage[pred_id]
        
        return {"message": f"学生 {student_id} 的数据已清除"}
        
    except Exception as e:
        logger.error(f"清除学生数据失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"清除学生数据失败: {str(e)}")


@router.get("/health")
async def health_check():
    """健康检查"""
    return {
        "status": "healthy",
        "service": "classroom_quality",
        "timestamp": datetime.now().isoformat(),
        "data_counts": {
            "attention_data": sum(len(data) for data in classroom_service.attention_data_storage.values()),
            "participation_data": sum(len(data) for data in classroom_service.participation_data_storage.values()),
            "classroom_analyses": len(classroom_service.classroom_analysis_storage),
            "learning_predictions": len(classroom_service.learning_predictions_storage)
        }
    }